package com.ge.util.commons.clouds;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class RunCodeClient {

	private Socket mSocket = null;
	
	private InputStream inStream = null;
	
	private OutputStream outStream = null;

	private boolean bSocketConnectSucc = false;
	
	private String strIp = null;
	
	private int nPort = 0;
	
	private long nTimeOut = 1000;
	
	public RunCodeClient(String strIp, int nPort) {
		this.strIp = strIp;
		this.nPort = nPort;
	}
	
	public void setTimeOut(long nTimeOut) {
		this.nTimeOut = nTimeOut;
	}
	
	public String getIp() {
		return strIp;
	}
	
	public int getPort() {
		return nPort;
	}
	
	public synchronized void connect() throws IOException {
		try {
			mSocket = new Socket(strIp, nPort);
			mSocket.setSoTimeout((int) nTimeOut);
			
			outStream = mSocket.getOutputStream();
			inStream = mSocket.getInputStream();
			
			bSocketConnectSucc = true;
		} catch (IOException e) {
			bSocketConnectSucc = false;
			throw e;
		}
	}
	
	public synchronized byte[] doFun(String strFunName, byte[] byArgs) throws CloudsException, IOException {
		doFun1(strFunName, byArgs);
		return doFun2();
	}

	public synchronized void doFun1(String strFunName, byte[] byArgs) throws IOException {
		try {
			IOStream.writeStringData(outStream, strFunName);
			IOStream.writeData(outStream, new IOStreamPacket(byArgs));
		} catch(IOException e) {
			bSocketConnectSucc = false;
			throw e;
		}
	}
	
	public synchronized byte[] doFun2() throws CloudsException, IOException {
		IOStreamPacket mPacket = null;
		try {
			mPacket = IOStream.readData(inStream);
		} catch(IOException e) {
			bSocketConnectSucc = false;
			throw e;
		}
		
		if (mPacket == null) {
			return null;
		}
		
		if (mPacket.byFlag == IOStreamPacket.SUCCESS) {
			return mPacket.byData;
		}

		if (mPacket.byFlag == IOStreamPacket.FUNCTION_EXCEPTION) {
			throw new CloudsException("FUNCTION_EXECUTION_EXCEPTION");
		}
		
		if (mPacket.byFlag == IOStreamPacket.FUNCTION_INVALID) {
			throw new CloudsException("FUNCTION_INVALID");
		}

		throw new CloudsException("FUNCTION_ID_ERROR");
	}
	
	public synchronized void close() {
		if (inStream != null) {
			try {
				inStream.close();
				inStream = null;
			} catch (IOException e) {
				//e.printStackTrace();
			}
		}
		
		if (outStream != null) {
			try {
				outStream.close();
				outStream = null;
			} catch (IOException e) {
				//e.printStackTrace();
			}
		}
		
		if (mSocket != null) {
			try {
				mSocket.close();
				mSocket = null;
			} catch (IOException e) {
				//e.printStackTrace();
			}
		}
		
		bSocketConnectSucc = false;
	}
	
	public synchronized boolean isConnect() {
		return bSocketConnectSucc;
	}

	public String toString() {
		return strIp + " : " + nPort;
	}
}
